<?php

/**
 * Folder class. Drop in replacement for Directory, and with some more features added.
 * 
 * Usage:
 * <code>
 * $test = new nuc_Folder(dirname(__FILE__).'/../');
 * $files = $test->getAllFiles(true);
 * foreach($files as $file)
 *   print md5_file($file)." - ".$file."\n";
 * </code>
 *
 */
class nuc_Folder extends Directory
{
	/**
	 * Path to folder
	 *
	 * @var string
	 */
	protected $folder = false;
	
	/**
	 * Resource handle to opened folder.
	 *
	 * @var resource
	 */
	protected $resource = null;
	
	/**
	 * Contents of folder. Format is array( 'folders' => array(...), 'files' => array(...) );
	 *
	 * @var array
	 */
	protected $contents = false;
	
	public function __construct($folder)
	{
		$this->folder = $folder;
	}
	
	/**
	 * Open folder resource
	 *
	 */
	protected function open()
	{
		$this->resource = opendir($this->folder);
	}
	
	
	/**
	 * Close folder resource
	 */
	public function close()
	{
		return closedir($this->resource);
	}
	
	/**
	 * Read directory next directory resource. Use getFolders/getFiles functions instead. 
	 * Here for compability with Directory class.
	 *
	 * @return mixed
	 */
	public function read()
	{
		return readdir($this->resource);
	}
	
	/**
	 * Rewind directory resource. Use getFolders/getFiles functions instead.
	 * Here for compability with Directory class.
	 *
	 * @return mixed
	 */
	public function rewind()
	{
		return rewinddir($this->resource);
	}
	
	/**
	 * Get contents of folder.
	 *
	 * @todo Result saved in contents. Return that directly if it's populated.
	 *  
	 * @param boolean $relative
	 * @return array
	 */
	protected function getContents($relative = true)
	{
		$this->open();
		
		$pre = ($relative?'':$this->folder);
		
		//rewinddir($this->resource);
		$this->contents = array(
			'folders' => array(),
			'files' => array()
		);
		
		while(false !== ($file = readdir($this->resource)))
		{
			if($file == '.' || $file == '..')
				continue;
			else if(is_dir($this->folder.$file))
				$this->contents['folders'][] = $pre.$file.'/';
			else
				$this->contents['files'][] = $pre.$file;
		}
		
		$this->close();
		
		return $this->contents;
	}
	
	/**
	 * Get subfolders for folder
	 *
	 * @param $relative Decides if paths in array are relative or absolute.
	 * @return array
	 */
	public function getSubfolders($relative = true)
	{
		$contents = $this->getContents($relative);
		
		return $contents['folders'];
	}
	
	/**
	 * Get all subfolders and their subfolders for folder. Fully recursive.
	 *
	 * @param $relative Decides if paths in array are relative or absolute.
	 * @return array
	 */
	public function getAllSubfolders($relative = true)
	{
		$ret = array();
		
		$pre = ($relative?'':$this->folder);
		
		foreach($this->getSubfolders() as $path)
		{
			$folder  = new nuc_Folder($this->folder.$path);
			$folders = $folder->getAllSubfolders();
			
			foreach($folders as $key => $val)
				$folders[$key] = $pre.$path.$val;
			
			$ret = array_merge($ret, $folders);
			
			$ret[] = $pre.$path;
		}
		return $ret;
	}
	
	/**
	 * Get files in folder
	 *
	 * @param $relative Decides if paths in array are relative or absolute.
	 * 
	 * @return array
	 */
	public function getFiles($relative = true)
	{
		$contents = $this->getContents($relative);
		
		return $contents['files'];
	}
	
	/**
	 * Get all files in folder with subfolders. Fully recursive.
	 * 
	 * @param $relative Decides if paths in array are relative or absolute.
	 *
	 * @return array
	 */
	public function getAllFiles($relative = true)
	{
		$ret = $this->getFiles($relative);
		
		$pre = ($relative?'':$this->folder);
		
		foreach($this->getAllSubfolders() as $path)
		{
			$folder = new nuc_Folder($this->folder.$path);
			$files = $folder->getFiles();

			foreach($files as $key => $val)
				$files[$key] = $pre.$path.$val;
			
			$ret = array_merge($ret, $files);
		}
		
		return $ret;
	}
}

?>